package pe.edu.unmsm.ocaa.workspace.presentacion.controller.login;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.annotation.Resource;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.primefaces.event.FileUploadEvent;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;
import org.springframework.context.annotation.Scope;
import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationException;
import org.springframework.security.AuthenticationManager;
import org.springframework.security.context.HttpSessionContextIntegrationFilter;
import org.springframework.security.context.SecurityContext;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.security.ui.AbstractProcessingFilter;
import org.springframework.security.ui.WebAuthenticationDetails;
import org.springframework.security.ui.webapp.AuthenticationProcessingFilter;
import org.springframework.stereotype.Controller;

import pe.edu.unmsm.ocaa.workspace.negocio.modelo.dto.ArchivoDTO;
import pe.edu.unmsm.ocaa.workspace.negocio.modelo.dto.UsuarioDTO;
import pe.edu.unmsm.ocaa.workspace.negocio.modelo.dto.VentanaPrincipalDTO;
import pe.edu.unmsm.ocaa.workspace.negocio.servicio.ArchivoService;
import pe.edu.unmsm.ocaa.workspace.negocio.servicio.UsuarioService;

@Controller
@Scope("session")
public class LoginController {

	/*****************ATRIBUTOS**************/
	private UsuarioDTO usuario;
	private boolean permisoadmin;
	private boolean permisodoc;
	private boolean permisodel;
	private String dirMenu;
	private VentanaPrincipalDTO ventanaPrincipal;
	private ArchivoDTO archivoSubidoDTO;
	private StreamedContent image;
	
	
	@Resource(name="MyAuthenticationManager")
	private AuthenticationManager authenticationManager;
	
	@Resource
	UsuarioService usuServ;
	@Resource
	ArchivoService archivoService;
	
	/*****************INICIALIZACION**************/
	public LoginController() {
		setUsuario(new UsuarioDTO());
		setArchivoSubidoDTO(new ArchivoDTO());
	}
	
	/*****************NAVEGACION**************/
	public void cerrarSesion(ActionEvent event)throws Exception{
		String out=cerrarSesionGeneric();
	}
	public String listarUsuarios(){
		return "listUsuario";
	}	
	public String cerrarSesionGeneric() {
		try {
			HttpSession se2=(HttpSession)FacesContext.getCurrentInstance().getExternalContext().getSession(false);
	    	se2.invalidate();			
		} catch (Exception e) {
			e.printStackTrace();
		}

		return "error";
	}
	
	public String iraRegUsuario(){
		HttpSession session=(HttpSession)FacesContext.getCurrentInstance().getExternalContext().getSession(true);
		//UsuarioDTO usuario=(UsuarioDTO)session.getAttribute("usuarioEditar");
		session.removeAttribute("usuarioEditar");
		return "regUsuario";
	}

	public String iraGestionArchivo(){
		return "gestionArchivo";
	}
	
	public String iraGestionAgenda(){
		return "gestionPrograma";
	}
	
	public String iraGestGrupo(){
		return "gestionGrupo";
	}
	
	public String iraManteVentP(){
		try {
			cargarImagen();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return "manteVentP";
	}
	
	public String loginActionAdmin() throws Exception
	{
		try{
			Authentication aut=validarContextSecurity(usuario.getNickUsuario(), usuario.getPswUsuario());
	    	if(aut.isAuthenticated()){	    		
	    		setUsuario(usuServ.obtenerUsuarioxNik(usuario.getNickUsuario()));
	    		setDirMenu(usuServ.obtenerDireccionMenu(usuario.getPerfilUsuario()));
	    		HttpSession session=(HttpSession)FacesContext.getCurrentInstance().getExternalContext().getSession(true);
				session.setAttribute("usuarioLogueado", usuario);
				setVentanaPrincipal(usuServ.obtenerVentanaPrincipalActual());
				cargarImagen();
	    		return "adminPrincipal";
	    	}else {
	    		return "error";
			}
		}catch(AuthenticationException e){
			return "error";	}
	}

	private void cargarImagen() throws FileNotFoundException {
		try {
			File file = new File("C:\\ocaa\\" + getVentanaPrincipal().getDescTitulo2());
			InputStream stream = new FileInputStream(file);
			//InputStream stream = this.getClass().getResourceAsStream("C:\\ocaa\\"+getVentanaPrincipal().getDescTitulo2());
			image = new DefaultStreamedContent(stream, "image/jpeg");			
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public Authentication validarContextSecurity(String usu, String pas)
	{
		HttpServletRequest request= getRequest();
		UsernamePasswordAuthenticationToken authReq=new UsernamePasswordAuthenticationToken(usu, pas);
    	authReq.setDetails(new WebAuthenticationDetails(request));			    	
    	HttpSession session = request.getSession();

    	session.setAttribute(AuthenticationProcessingFilter.SPRING_SECURITY_LAST_USERNAME_KEY, usu);
    	Authentication auth = getAuthenticationManager().authenticate(authReq);
        
    	SecurityContext secCtx = SecurityContextHolder.getContext();	    	
    	secCtx.setAuthentication(auth);
    	session.setAttribute(HttpSessionContextIntegrationFilter.SPRING_SECURITY_CONTEXT_KEY, secCtx);   			    	

    	String urlKey = AbstractProcessingFilter.SPRING_SECURITY_SAVED_REQUEST_KEY;	   
    	//SavedRequest savedRequest = (SavedRequest)session.getAttribute(urlKey);
    	session.removeAttribute(urlKey);
    	return auth ;
	}
	
	private HttpServletRequest getRequest() {
		return (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
	}

	public void guardarVentanaPrincipal(ActionEvent ev){
		try {
			usuServ.guardarVentanaPrincipal(getVentanaPrincipal());
			FacesMessage msg = new FacesMessage("Exito","Se guardo correctamente los cambios.");        
	        FacesContext.getCurrentInstance().addMessage(null, msg);			
		} catch (Exception e) {
			FacesMessage msg = new FacesMessage("Oops","Hubo un error al guardar los cambios.");        
	        FacesContext.getCurrentInstance().addMessage(null, msg);
		}

	}
	
	/*********************METODOS DE SUBIR ARCHIVOS DEBEN IR A UN SERVICIO**************************/
    public void subirArchivo(FileUploadEvent event) throws IOException {
        if(!existeArchivo(event))
        {
        	String nombreArchivoDisco=archivoService.generarSgteNomArchivoDisco(event.getFile().getFileName());
        	guardarArchivoFisico(nombreArchivoDisco, event.getFile().getInputstream());
            guardarArchivoBD(event, nombreArchivoDisco);
            FacesMessage msg = new FacesMessage("Exito", event.getFile().getFileName() + " esta archivo no tiene errores.");        
            FacesContext.getCurrentInstance().addMessage(null, msg);	
            getVentanaPrincipal().setDescTitulo2(nombreArchivoDisco);
            cargarImagen();
        }
        else
        {
        	FacesMessage msg = new FacesMessage("Aviso","El " + event.getFile().getFileName() + " ya existe.");        
            FacesContext.getCurrentInstance().addMessage(null, msg);
        }
    }

	private boolean existeArchivo(FileUploadEvent event) {
		Integer idPadre;
		idPadre=0;
		return archivoService.existeArchivoenCarpeta(event.getFile().getFileName(), idPadre);
	}

	private void guardarArchivoBD(FileUploadEvent event, String nombreArchivoDisco) {
		getArchivoSubidoDTO().setNombreArchivoDisco(nombreArchivoDisco);
		getArchivoSubidoDTO().setNombreArchivoVirtual(event.getFile().getFileName());
        getArchivoSubidoDTO().setIdArchivoPadre(86);
        archivoService.guardarArchivo(getArchivoSubidoDTO());
	}  	
    
    
	public void guardarArchivoFisico(String fileName, InputStream in) {
		try {
			String destination = "C:\\ocaa\\";
			// write the inputStream to a FileOutputStream
			OutputStream out = new FileOutputStream(new File(destination
					+ fileName));

			int read = 0;
			byte[] bytes = new byte[1024];

			while ((read = in.read(bytes)) != -1) {
				out.write(bytes, 0, read);
			}

			in.close();
			out.flush();
			out.close();
		} catch (IOException e) {
			System.out.println(e.getMessage());
		}
	}
	
	
	/*****************GETTERS AND SETTERS**************/
	public UsuarioDTO getUsuario() {
		return usuario;
	}

	public void setUsuario(UsuarioDTO usuario) {
		this.usuario = usuario;
	}

	public boolean isPermisodel() {
		return permisodel;
	}

	public void setPermisodel(boolean permisodel) {
		this.permisodel = permisodel;
	}

	public boolean isPermisodoc() {
		return permisodoc;
	}

	public void setPermisodoc(boolean permisodoc) {
		this.permisodoc = permisodoc;
	}

	public boolean isPermisoadmin() {
		return permisoadmin;
	}

	public void setPermisoadmin(boolean permisoadmin) {
		this.permisoadmin = permisoadmin;
	}

	public AuthenticationManager getAuthenticationManager() {
		return authenticationManager;
	}

	public void setAuthenticationManager(AuthenticationManager authenticationManager) {
		this.authenticationManager = authenticationManager;
	}

	public String getDirMenu() {
		return dirMenu;
	}

	public void setDirMenu(String dirMenu) {
		this.dirMenu = dirMenu;
	}

	public VentanaPrincipalDTO getVentanaPrincipal() {
		return ventanaPrincipal;
	}

	public void setVentanaPrincipal(VentanaPrincipalDTO ventanaPrincipal) {
		this.ventanaPrincipal = ventanaPrincipal;
	}

	public ArchivoDTO getArchivoSubidoDTO() {
		return archivoSubidoDTO;
	}

	public void setArchivoSubidoDTO(ArchivoDTO archivoSubidoDTO) {
		this.archivoSubidoDTO = archivoSubidoDTO;
	}

	public StreamedContent getImage() {
		return image;
	}

	public void setImage(StreamedContent image) {
		this.image = image;
	}
}
